﻿using AngleSharp.Dom;
using AutoMapper;
using NewLife.Redis.Core;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WomanMotion.WebApi.Infrastructure.YitId;
using WomanMotion.WebApi.Model.Dtos.Authoritys;
using WomanMotion.WebApi.Model.Dtos.Role;
using WomanMotion.WebApi.Model.Entitys;
using WomanMotion.WebApi.Repository.IRepository;

namespace WomanMotion.WebApi.Repository.Repository
{
    /// <summary>
    /// 角色数据工厂类
    /// </summary>
    public class RoleRepository : BaseRepository<Role>, IRoleRepository
    {
        private readonly IMapper _mapper;
        private readonly IActionsRepository _actionsRepository;
        private readonly IAuthoritysRepository _authoritysRepository;
        private readonly INewLifeRedis _newLifeRedis;

        public RoleRepository(ISqlSugarClient db, IMapper mapper, IActionsRepository actionsRepository, IAuthoritysRepository authoritysRepository, INewLifeRedis newLifeRedis) : base(db)
        {
            _mapper = mapper;
            _actionsRepository = actionsRepository;
            _authoritysRepository = authoritysRepository;
            _newLifeRedis = newLifeRedis;
        }

        /// <summary>
        /// 添加角色，因为涉及到添加权限，所以使用事务(异步)
        /// </summary>
        /// <param name="dto">dto</param>
        /// <param name="userid">用户id</param>
        /// <returns></returns>
        public virtual async Task<RoleVM> InsertAsync(CreatedRoleDTO dto, long userid)
        {
            Dictionary<long, long> ConAndAction = await GetActAndConDic(dto.authoritystree);
            var entity = _mapper.Map<CreatedRoleDTO, Role>(dto);
            entity.Id = YitIdHelper.NextId();
            entity.Ifdisable = 1;
            entity.Createdby = userid;
            entity.Updatedby = userid;
            entity.Createdtime = DateTime.Now;
            entity.Updatedtime = DateTime.Now;
            try
            {
                _db.Ado.BeginTran();
                var role = await _db.Insertable(entity).ExecuteReturnEntityAsync();
                foreach (var item in ConAndAction)
                {
                    var atth = new Authoritys() { Id = YitIdHelper.NextId(), Roleid = role.Id, Controllerid = item.Value, Actionsid = item.Key };
                    await _db.Insertable(atth).ExecuteReturnEntityAsync();
                }
                _db.Ado.CommitTran();
                //查询此角色权限并加入缓存
                var atths = await GetCommonListAsync<AuthoritysPageVM>(_db.Queryable<Authoritys>()
                .InnerJoin<Role>((auth, role) => auth.Roleid == role.Id)
                .InnerJoin<Controller>((auth, role, conl) => auth.Controllerid == conl.Id)
                .InnerJoin<Actions>((auth, role, conl, act) => auth.Actionsid == act.Id)
                .Select((auth, role, conl, act) =>
                    new AuthoritysPageVM()
                    {
                        Id = auth.Id,
                        Roleid = role.Id,
                        RoleCode = role.Code,
                        RoleName = role.Name,
                        Controllerid = auth.Controllerid,
                        ControllerCode = conl.Code,
                        ControllerName = conl.Name,
                        Actionsid = auth.Actionsid,
                        ActionsCode = act.Code,
                        ActionsName = act.Name
                    }).MergeTable().Where(m => m.Roleid == role.Id));
                foreach (var atth in atths)
                {
                    var redisname = "auth_" + atth.RoleCode + "_" + atth.ControllerCode + "_" + atth.ActionsCode;
                    var redisvalue = new AuthoritysReids() { RoleCode = atth.RoleCode, ControllerCode = atth.ControllerCode, ActionsCode = atth.ActionsCode };
                    //如果存在缓存先移除
                    _newLifeRedis.Remove(redisname);
                    //然后在添加保证是最新权限
                    _newLifeRedis.Set(redisname, redisvalue);
                }
                var vm = _mapper.Map<Role, RoleVM>(entity);
                return vm;
            }
            catch (Exception ex)
            {
                _db.Ado.RollbackTran();
                return null;
            }
        }

        /// <summary>
        /// 更新角色，因为涉及到添加权限，所以使用事务(异步)
        /// </summary>
        /// <param name="dto">dto</param>
        /// <param name="userid">用户id</param>
        /// <returns></returns>
        public virtual async Task<RoleVM> UpdateAsync(UpdateRoleDTO dto, long userid)
        {
            //查询出此角色的所有缓存并删除
            var atths = await GetCommonListAsync<AuthoritysPageVM>(_db.Queryable<Authoritys>()
                .InnerJoin<Role>((auth, role) => auth.Roleid == role.Id)
                .InnerJoin<Controller>((auth, role, conl) => auth.Controllerid == conl.Id)
                .InnerJoin<Actions>((auth, role, conl, act) => auth.Actionsid == act.Id)
                .Select((auth, role, conl, act) =>
                    new AuthoritysPageVM()
                    {
                        Id = auth.Id,
                        Roleid = role.Id,
                        RoleCode = role.Code,
                        RoleName = role.Name,
                        Controllerid = auth.Controllerid,
                        ControllerCode = conl.Code,
                        ControllerName = conl.Name,
                        Actionsid = auth.Actionsid,
                        ActionsCode = act.Code,
                        ActionsName = act.Name
                    }).MergeTable().Where(m => m.Roleid == dto.Id));
            foreach (var atth in atths)
            {
                var redisname = "auth_" + atth.RoleCode + "_" + atth.ControllerCode + "_" + atth.ActionsCode;
                //如果存在缓存先移除
                _newLifeRedis.Remove(redisname);
            }
            //dto转换实体
            var entity = _mapper.Map<UpdateRoleDTO, Role>(dto);
            //通过ID查询实体
            var entitytemp = await GetByIDAsync(dto.Id);
            if (entitytemp == null)
            {
                return default(RoleVM);
            }
            entity.Createdby = entitytemp.Createdby;
            entity.Createdtime = entitytemp.Createdtime;
            entity.Updatedby = userid;
            entity.Updatedtime = DateTime.Now;
            Dictionary<long, long> ConAndAction = await GetActAndConDic(dto.authoritystree);
            try
            {
                _db.Ado.BeginTran();
                var res = await _db.Updateable(entity).ExecuteCommandAsync();
                if (res <= 0)
                {
                    _db.Ado.RollbackTran();
                    return default(RoleVM);
                }
                //删除所有此角色的权限
                await _db.Deleteable<Authoritys>().Where(m => m.Roleid == dto.Id).ExecuteCommandAsync();
                //插入权限表数据
                foreach (var item in ConAndAction)
                {
                    var atth = new Authoritys() { Id = YitIdHelper.NextId(), Roleid = dto.Id, Controllerid = item.Value, Actionsid = item.Key };
                    await _db.Insertable(atth).ExecuteReturnEntityAsync();
                }
                _db.Ado.CommitTran();
                //查询此角色权限并加入缓存
                var atthsnew = await GetCommonListAsync<AuthoritysPageVM>(_db.Queryable<Authoritys>()
                .InnerJoin<Role>((auth, role) => auth.Roleid == role.Id)
                .InnerJoin<Controller>((auth, role, conl) => auth.Controllerid == conl.Id)
                .InnerJoin<Actions>((auth, role, conl, act) => auth.Actionsid == act.Id)
                .Select((auth, role, conl, act) =>
                    new AuthoritysPageVM()
                    {
                        Id = auth.Id,
                        Roleid = role.Id,
                        RoleCode = role.Code,
                        RoleName = role.Name,
                        Controllerid = auth.Controllerid,
                        ControllerCode = conl.Code,
                        ControllerName = conl.Name,
                        Actionsid = auth.Actionsid,
                        ActionsCode = act.Code,
                        ActionsName = act.Name
                    }).MergeTable().Where(m => m.Roleid == dto.Id));
                foreach (var atth in atthsnew)
                {
                    var redisname = "auth_" + atth.RoleCode + "_" + atth.ControllerCode + "_" + atth.ActionsCode;
                    var redisvalue = new AuthoritysReids() { RoleCode = atth.RoleCode, ControllerCode = atth.ControllerCode, ActionsCode = atth.ActionsCode };
                    //如果存在缓存先移除
                    _newLifeRedis.Remove(redisname);
                    //然后在添加保证是最新权限
                    _newLifeRedis.Set(redisname, redisvalue);
                }
                var vm = _mapper.Map<Role, RoleVM>(entity);
                return vm;
            }
            catch (Exception ex)
            {
                _db.Ado.RollbackTran();
                return null;
            }
        }

        private async Task<Dictionary<long, long>> GetActAndConDic(string[] strs)
        {
            Dictionary<long, long> ConAndAction = new Dictionary<long, long>();
            if (strs != null && strs.Length > 0)
            {
                //查询数组里面的action数据
                var acs = from str in strs where str.Contains("action") select str;
                var actionIDS = new List<long>();
                //取出方法id
                foreach (var a in acs)
                {
                    string[] strArray = a.Split(',');
                    actionIDS.Add(long.Parse(strArray[1]));
                }
                //循环actionIDS
                foreach (var actionid in actionIDS)
                {
                    //查询控制器id
                    var con = await _actionsRepository.GetAsync(m => m.Id == actionid);
                    var conid = con.Controllerid;
                    ConAndAction.Add(actionid, conid);
                }
            }
            return ConAndAction;
        }
    }
}